package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.dto.StatisticsRefundDto;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.enums.RefundType;
import com.yami.shop.bean.enums.ReturnMoneyStsType;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.PayTopParam;
import com.yami.shop.bean.param.ProdAnalysisSurveyParam;
import com.yami.shop.bean.vo.OrderDetailVO;
import com.yami.shop.bean.vo.OrderItemDetailVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.dao.OrderItemMapper;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.dao.OrderRefundMapper;
import com.yami.shop.manager.impl.LangManager;
import com.yami.shop.service.OrderItemService;
import lombok.AllArgsConstructor;
import com.yami.shop.common.util.BeanUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Service
@AllArgsConstructor
public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem> implements OrderItemService {

    private final OrderItemMapper orderItemMapper;

    private final RedissonClient redissonClient;

    private final OrderMapper orderMapper;

    private final OrderRefundMapper orderRefundMapper;



    private final LangManager langManager;

    @Override
    public List<OrderItem> getOrderItemsByOrderNumber(String orderNumber) {
        return orderItemMapper.listByOrderNumber(orderNumber);
    }

    @Override
    public List<OrderItem> getUnGiveawayOrderItemsByOrderNumber(String orderNumber) {
        return orderItemMapper.getUnGiveawayOrderItemsByOrderNumber(orderNumber);
    }

    @Override
    public IPage<PayTopParam> getPayAmounts(PageParam<OrderItem> page, ProdAnalysisSurveyParam param) {
        IPage<PayTopParam> resPage = orderItemMapper.getPayAmounts(page, param);
        List<Long> prodIds = resPage.getRecords().stream().filter(payTopParam -> Objects.nonNull(payTopParam.getProdId())).map(PayTopParam::getProdId).collect(Collectors.toList());
        Map<Long, ProdLang> prodLangMap = langManager.getProdLangMap(prodIds);
        for (PayTopParam payTopParam : resPage.getRecords()) {
            ProdLang prodLang = prodLangMap.get(payTopParam.getProdId());
            if (Objects.nonNull(prodLang)) {
                payTopParam.setProdName(prodLang.getProdName());
            }
        }
        return resPage;
    }

    @Override
    public Integer getPayPersonNumByParam(Long prodId, Long shopId, Date startTime, Date endTime) {
        return orderItemMapper.getPayPersonNumByParam(prodId, shopId, startTime, endTime);
    }

    @Override
    public void insertBatchOrderItem(List<OrderItem> orderItems) {
        saveBatch(orderItems);
        // orderItemMapper.insertBatchOrderItemLang(orderItems);
    }

    @Override
    public OrderItem getByOrderItemId(Long orderItemId) {
        return orderItemMapper.getByOrderItemId(orderItemId);
    }

    @Override
    public OrderItem getOrderItemAndRefundByOrderItemId(Long orderItemId) {
        return orderItemMapper.getInfoByOrderItemId(orderItemId);
    }

    @Override
    public OrderDetailVO listDetailByParam(String orderNumber, String refundSn) {
        Order order = orderMapper.getOrderByOrderNumber(orderNumber);
        OrderDetailVO orderDetailVO = BeanUtil.map(order, OrderDetailVO.class);
        // 订单项信息
        List<OrderItemDetailVO> orderItems = orderItemMapper.listDetailByOrderNumber(orderNumber, order.getShopId());
        List<Long> categoryIds = orderItems.stream().filter(orderItem -> Objects.nonNull(orderItem.getCategoryId())).map(OrderItemDetailVO::getCategoryId).collect(Collectors.toList());
        Map<Long, CategoryLang> categoryLangMap = langManager.getCategoryLangMap(categoryIds);
        List<OrderItemDetailVO> orderItemDetailList = new ArrayList<>();
        OrderRefund orderRefundVO = null;
        if (StrUtil.isNotBlank(refundSn)) {
            orderRefundVO = orderRefundMapper.getOrderRefundByRefundSn(refundSn);
        }
        List<String> giveawayIds = new ArrayList<>();
        if (Objects.nonNull(orderRefundVO)) {
            String returnGiveawayIds = orderRefundVO.getReturnGiveawayIds();
            if (Objects.nonNull(returnGiveawayIds)) {
                giveawayIds = Arrays.asList(returnGiveawayIds.split(","));
            }
        }
        for (OrderItemDetailVO detailVO : orderItems) {
            CategoryLang categoryLang = categoryLangMap.get(detailVO.getCategoryId());
            if (Objects.nonNull(categoryLang)) {
                detailVO.setCategoryName(categoryLang.getCategoryName());
            }
            if (Objects.equals(order.getOrderType(), OrderType.SECKILL.value())) {
                detailVO.setSeckillAmount(detailVO.getMultishopReduce());
            } else if (Objects.equals(order.getOrderType(), OrderType.GROUP.value())) {
                detailVO.setGroupAmount(detailVO.getMultishopReduce());
            }
            if (Objects.equals(order.getShopId(), Constant.PLATFORM_SHOP_ID)) {
                detailVO.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
            OrderItemDetailVO orderItemDetailVO = BeanUtil.map(detailVO, OrderItemDetailVO.class);
            orderItemDetailVO.setRefundAmount(0.00);
            if (Objects.isNull(orderItemDetailVO.getPlatformShareReduce())) {
                orderItemDetailVO.setPlatformShareReduce(0.00);
            }
            orderItemDetailVO.setRefundCount(0);
            if (Objects.nonNull(orderRefundVO) && Objects.equals(orderRefundVO.getOrderItemId(), 0L)) {
                orderItemDetailVO.setRefundCount(detailVO.getProdCount());
                orderItemDetailVO.setRefundAmount(detailVO.getActualTotal());
            } else if (Objects.nonNull(orderRefundVO) && !Objects.equals(orderRefundVO.getOrderItemId(), 0L)) {
                if (Objects.equals(orderRefundVO.getOrderItemId(), detailVO.getOrderItemId())) {
                    orderItemDetailVO.setRefundCount(orderRefundVO.getGoodsNum());
                    orderItemDetailVO.setRefundAmount(orderRefundVO.getRefundAmount());
                }
                //赠品
                if (CollUtil.isNotEmpty(giveawayIds) && giveawayIds.contains(detailVO.getOrderItemId().toString())) {
                    orderItemDetailVO.setRefundCount(orderRefundVO.getGoodsNum());
                }
            }
            orderItemDetailList.add(orderItemDetailVO);
        }
        orderDetailVO.setOrderItemDetailList(orderItemDetailList);
        orderDetailVO.setFreeFreightAmount(order.getFreeTransfee());
        orderDetailVO.setPlatformFreeFreightAmount(order.getPlatformFreeFreightAmount());
        orderDetailVO.setFreightAmount(order.getFreightAmount());
        return orderDetailVO;
    }

    @Override
    public Integer getOrderItemProdNum(Long orderItemId) {
        return orderItemMapper.getOrderItemProdNum(orderItemId);
    }

    @Override
    public OrderItem getByIdI18n(Long orderItemId) {
        return orderItemMapper.getByOrderItemId(orderItemId);
    }

    @Override
    public List<OrderItem> listAndPayTimeByOrderNumber(String orderNumber) {
        List<OrderItem> orderItems = orderItemMapper.listAndPayTimeByOrderNumber(orderNumber);
        Set<Long> refundOrderItemIdSet = new HashSet<>();
        for (OrderItem orderItem : orderItems) {
            // 找出退款成功的订单项（退款成功的订单项无法评价）
            if (Objects.equals(orderItem.getRefundType(), RefundType.SINGLE.value()) && Objects.equals(orderItem.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value())) {
                refundOrderItemIdSet.add(orderItem.getOrderItemId());
                if (StrUtil.isNotBlank(orderItem.getReturnGiveawayIds())) {
                    String returnGiveawayIds = orderItem.getReturnGiveawayIds();
                    String[] giveawayIds = returnGiveawayIds.split(StrUtil.COMMA);
                    for (String giveawayId : giveawayIds) {
                        refundOrderItemIdSet.add(Long.parseLong(giveawayId));
                    }
                }
            }
        }
        if (CollectionUtil.isNotEmpty(refundOrderItemIdSet)) {
            Iterator<OrderItem> iterator = orderItems.iterator();
            while (CollectionUtil.isNotEmpty(refundOrderItemIdSet)){
                OrderItem orderItem = iterator.next();
                if (refundOrderItemIdSet.contains(orderItem.getOrderItemId())){
                    iterator.remove();
                    refundOrderItemIdSet.remove(orderItem.getOrderItemId());
            }
        }
    }
        return orderItems;
}

    @Override
    public List<PayTopParam> getOrderProdPayCount(StatisticsRefundDto statisticsRefundDto) {
        if (Objects.isNull(statisticsRefundDto.getSize())) {
            statisticsRefundDto.setSize(10);
        }
        return orderItemMapper.getOrderProdPayCount(statisticsRefundDto);
    }
    @Override
    public List<Long> getSoldNumRankByShopIdAndTime(String key, Long shopId, Integer dayNum, Integer expireTime, Integer esRenovationSpuSort) {
        Date time = null;
        if(dayNum != 0) {
            time = DateUtil.offsetDay(new DateTime(), -dayNum);
        }

        List<Long> spuIds = RedisUtil.getListRange(key,0L,10L);
        if (CollectionUtil.isNotEmpty(spuIds)) {
            return spuIds;
        }

        // 加锁，防止缓存击穿
        RLock rLock = redissonClient.getLock("redisson_lock:sold_num_rank:" + key);
        try {
            int lockWait = 30;
            if (rLock.tryLock(lockWait, lockWait, TimeUnit.SECONDS)) {
                spuIds = RedisUtil.getListRange(key,0L,10L);
                if (CollectionUtil.isEmpty(spuIds)) {
                    spuIds = orderItemMapper.getSoldNumRankByShopIdAndTime( shopId, time,  esRenovationSpuSort);
                    return spuIds;
                }
            } else {
                throw new YamiShopBindException("网络繁忙，请稍后再试");
            }
        } catch (InterruptedException e) {
            log.error("InterruptedException:", e);
        } finally {
            try {
                if (rLock.isLocked()) {
                    rLock.unlock();
                }
            } catch (Exception e) {
                log.error("Exception:", e);
            }
        }
        return spuIds;
    }

//    @Override
//    public List<OrderItem> getUnCloseRefundOrderItemByOrderNumber(String orderNumber) {
//        return orderItemMapper.getUnCloseRefundOrderItemByOrderNumber(orderNumber);
//    }

}
